package cc.mrbird.febs.mark.controller;

import cc.mrbird.febs.common.annotation.ControllerEndpoint;
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.common.utils.JiebaSegWords;
import cc.mrbird.febs.mark.entity.Railway;
import cc.mrbird.febs.mark.service.IRailwayService;

import cc.mrbird.febs.system.entity.User;
import cc.mrbird.febs.system.service.IUserService;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.wuwenze.poi.ExcelKit;
import com.wuwenze.poi.handler.ExcelReadHandler;
import com.wuwenze.poi.pojo.ExcelErrorField;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
@Validated
@RestController
@RequestMapping("railway")
public class RailwayController extends BaseController {
    @Autowired
    private IRailwayService railwayService;

    @Autowired
    private IUserService userService;
//    @GetMapping("{railwayId}")
//    public Railway getRailway(@NotBlank(message = "{required}") @PathVariable String railwayId){
//        return this.railwayService.getById(railwayId);
//    }

    @GetMapping("list")
    @RequiresPermissions("railway:view")
    public FebsResponse railwayList( QueryRequest request,Railway railway) {
        //获取的railwaylist为自己的而且是已经分派过的
        User currentUser = FebsUtil.getCurrentUser();
        railway.setStuNo(currentUser.getStuNo());
        railway.setIsAssign("1");
        Map<String, Object> dataTable = getDataTable(this.railwayService.findRailways(request,railway ));
        return new FebsResponse().success().data(dataTable);
    }

    
    @GetMapping("listEl/{tag}")
    @RequiresPermissions("railway:view")
    /**
    * @Description 获取分词校对过的railway列表，用来进行实体标注，即只有进行过分词校对才能进行实体标注，没有校对过的先进行分词校对再进行实体标注
    * @param request
    * @param railway
    * @return cc.mrbird.febs.common.entity.FebsResponse
    * @Author wgw
    * @Date 2019-10-29
    * @Time 11:20
    */
    public FebsResponse railwayListEl( @PathVariable String tag,QueryRequest request,Railway railway) {
        railway.setIsSeg("1");
        railway.setTag(tag);
        return railwayList(request,railway);
    }

    @GetMapping("listQA")
    @RequiresPermissions("railway:view")
    /***
    * @Description 获取分词校对过的railway列表，用来进行问答
    * @param request
    * @param railway
    * @return cc.mrbird.febs.common.entity.FebsResponse
    * @Author wgw
    * @Date 2019-11-14
    * @Time 13:26
    */
    public FebsResponse railwayListQA( QueryRequest request,Railway railway) {
        railway.setIsSeg("1");
        railway.setTag("QA");
        return railwayList(request,railway);
    }

    @PostMapping("getJiebaResult")
    public FebsResponse getSegwords(String originContent){
        String result=JiebaSegWords.getJiebaResult(originContent);
        return new FebsResponse().success().data(result);
    }

    @PostMapping("update")
    @RequiresPermissions("railway:update")
    @ControllerEndpoint(operation = "修改铁路文本", exceptionMessage = "修改铁路文本失败")
    public FebsResponse updateRailway(@Valid Railway railway) {
        if (railway.getRailwayId() == null)
            throw new FebsException("铁路文本ID为空");
        this.railwayService.updateRailway(railway);
        return new FebsResponse().success();
    }
    @PostMapping("updateSeg")
    @RequiresPermissions("railway:update")
    @ControllerEndpoint(operation = "修改铁路文本分词", exceptionMessage = "修改铁路文本分词失败")
    public FebsResponse updateRailwaySegWords(@Valid Railway railway) {
        return  updateRailway(railway);
    }

    @PostMapping("updateEl")
    @RequiresPermissions("railway:update")
    @ControllerEndpoint(operation = "修改铁路文本实体标注", exceptionMessage = "修改铁路文本实体标注失败")
    public FebsResponse updateRailwayEl(@Valid Railway railway) {
        return  updateRailway(railway);
    }

    @PostMapping("updateQA")
    @RequiresPermissions("railway:update")
    @ControllerEndpoint(operation = "修改铁路文本问答", exceptionMessage = "修改铁路文本问答失败")
    public FebsResponse updateRailwayQA(@Valid Railway railway) {
        return  updateRailway(railway);
    }

    @GetMapping("delete/{railwayIds}")
    @RequiresPermissions("railway:delete")
    @ControllerEndpoint(operation = "删除铁路文本", exceptionMessage = "删除铁路文本失败")
    public FebsResponse deleteRailways(@NotBlank(message = "{required}") @PathVariable String railwayIds) {
        String[] ids = railwayIds.split(StringPool.COMMA);
        this.railwayService.deleteRailways(ids);
        return new FebsResponse().success();
    }

    /**
     * 生成 Excel导入模板
     */
    @GetMapping("template")
    @RequiresPermissions("railway:template")
    public void generateImportTemplate(HttpServletResponse response) {
        // 构建数据
        List<Railway> list = new ArrayList<>();

        Railway railway = new Railway();
        railway.setFileName("test.xlsx");
        railway.setOriginContent("这是待标注的文本");
        list.add(railway);

        // 构建模板
        ExcelKit.$Export(Railway.class, response).downXlsx(list, true);
    }



    /**
     * 导入Excel数据，并批量插入 T_Railway表，平均分配给多个用户
     */
    @PostMapping("import")
    @RequiresPermissions("railway:import")
    @ControllerEndpoint(operation = "导入铁路文本从Excel",exceptionMessage = "导入Excel数据失败")
    public FebsResponse importExcels(MultipartFile file) throws IOException {

        final List<User> students=userService.getUsersExceptAdmin();

        return  importExcels(file,students);
    }

    /**
     * 导入Excel数据，并批量插入 T_Railway表，平均分配给多个用户
     */
    @PostMapping("importOne")
    @RequiresPermissions("railway:import")
    @ControllerEndpoint(operation = "导入铁路文本从Excel",exceptionMessage = "导入Excel数据失败")
    public FebsResponse importExcelsOne(MultipartFile file,String stuNo) throws IOException {
        List<User> students=new ArrayList<>();
        User u=null;
        if((u=userService.findByName(stuNo))!=null){
            students.add(u);
        }
        else {
            log.error("没有该学生！");
        }
        return  importExcels(file,students);
    }


    @ControllerEndpoint(operation = "导入铁路文本从Excel",exceptionMessage = "导入Excel数据失败")
    public FebsResponse importExcels(MultipartFile file,List<User> students) throws IOException {
        if (file.isEmpty()) {
            throw new FebsException("Excel文件没有数据");
        }
        String filename = file.getOriginalFilename();
        if (!StringUtils.endsWith(filename, ".xlsx")) {
            throw new FebsException("只支持.xlsx类型文件导入");
        }
        // 开始导入操作
        Stopwatch stopwatch = Stopwatch.createStarted();


        final List<Railway> data = Lists.newArrayList();
        final List<Map<String, Object>> error = Lists.newArrayList();
        ExcelKit.$Import(Railway.class).readXlsx(file.getInputStream(), new ExcelReadHandler<Railway>() {

            int studentIndex=0;int studentNumber=students.size();
            @Override
            public void onSuccess(int sheet, int row, Railway railway) {
                // 数据校验成功时，加入集合

                railway.setRailwayId(null);
                if(railway.getFileName()==null){
                    railway.setFileName(filename);
                }

                railway.setCreateTime(new Date());
                railway.setModifyTime(null);

                railway.setIsEntity("0");
                railway.setEntityWords(null);
                railway.setEntityWordsHtml(null);

                //因为要给学生使用，默认设置 分词校对为 已经校对过
                railway.setIsSeg("1");
                //结巴分词
                String jiebaResult=JiebaSegWords.getJiebaResult(railway.getOriginContent());
                railway.setSegWordsJieba(jiebaResult);
                railway.setSegWords(jiebaResult);
                railway.setSegWordsHtml(jiebaResult);

                //分配任务,循环分配给用户
                railway.setIsAssign("1");
                railway.setStuNo(students.get(studentIndex).getStuNo());
                railway.setRealname(students.get(studentIndex).getRealname());
                if(studentIndex<studentNumber-1){
                    studentIndex++;
                }else{
                    studentIndex=0;
                }
                data.add(railway);
            }

            @Override
            public void onError(int sheet, int row, List<ExcelErrorField> errorFields) {
                // 数据校验失败时，记录到 error集合
                error.add(ImmutableMap.of("row", row, "errorFields", errorFields));
            }
        });
        if (CollectionUtils.isNotEmpty(data)) {
            // 将合法的记录批量入库
            this.railwayService.batchInsert(data);
        }
        ImmutableMap<String, Object> result = ImmutableMap.of(
                "time", stopwatch.stop().toString(),
                "data", data,
                "error", error,
                "usercount",students.size()
        );
        return new FebsResponse().success().data(result);
    }


    @GetMapping("excel")
    @RequiresPermissions("railway:export")
    @ControllerEndpoint(operation = "导出铁路文本到Excel",exceptionMessage = "导出铁路文本到Excel失败")
    public void export(QueryRequest queryRequest, Railway railway, HttpServletResponse response) {
        try{
            List<Railway> railways = this.railwayService.findRailways(queryRequest, railway).getRecords();
            setE1E2(response, railways);
        }catch (Exception e){
            e.printStackTrace();
        }

//        导出铁路数据到本地文件中
//        List<Railway> railways = this.railwayService.findRailways();
//        railways.forEach(o->{
//            if(o.getIsEntity().equals("1")){
//                Pattern r1=Pattern.compile("<e1 (.*) /e1>");
//                Matcher m1=r1.matcher(o.getEntityWords());
//                if(m1.find()){
//                    o.setE1(m1.group(1));
//                }
//                Pattern r2=Pattern.compile("<e2 (.*) /e2>");
//                Matcher m2=r2.matcher(o.getEntityWords());
//                if(m2.find()){
//                    o.setE2(m2.group(1));
//                }
//            }
//
//        });
//
//        try{
//            FileOutputStream fileOutputStream=new FileOutputStream("/Users/wgw/railway.xlsx");
//            ExcelKit.$Builder(Railway.class, fileOutputStream).writeXlsx(railways, false);
//        }catch (Exception e){
//            e.printStackTrace();
//        }

    }
    @GetMapping("excelExportAll")
    @RequiresPermissions("railway:export")
    @ControllerEndpoint(operation = "导出全部铁路文本到Excel",exceptionMessage = "导出全部铁路文本到Excel失败")
    public void exportAll(QueryRequest queryRequest, Railway railway, HttpServletResponse response) {
        try{
            List<Railway> railways = this.railwayService.findRailways();
            setE1E2(response, railways);
        }catch (Exception e){
            e.printStackTrace();
        }

//        导出铁路数据到本地文件中
//        List<Railway> railways = this.railwayService.findRailways();
//        railways.forEach(o->{
//            if(o.getIsEntity().equals("1")){
//                Pattern r1=Pattern.compile("<e1 (.*) /e1>");
//                Matcher m1=r1.matcher(o.getEntityWords());
//                if(m1.find()){
//                    o.setE1(m1.group(1));
//                }
//                Pattern r2=Pattern.compile("<e2 (.*) /e2>");
//                Matcher m2=r2.matcher(o.getEntityWords());
//                if(m2.find()){
//                    o.setE2(m2.group(1));
//                }
//            }
//
//        });
//
//        try{
//            FileOutputStream fileOutputStream=new FileOutputStream("/Users/wgw/railway.xlsx");
//            ExcelKit.$Builder(Railway.class, fileOutputStream).writeXlsx(railways, false);
//        }catch (Exception e){
//            e.printStackTrace();
//        }

    }

    private void setE1E2(HttpServletResponse response, List<Railway> railways) {
        railways.forEach(o->{
            if(o.getIsEntity().equals("1")){
                Pattern r1=Pattern.compile("<e1 (.*) /e1>");
                Matcher m1=r1.matcher(o.getEntityWords());
                if(m1.find()){
                    o.setE1(m1.group(1));
                }
                Pattern r2=Pattern.compile("<e2 (.*) /e2>");
                Matcher m2=r2.matcher(o.getEntityWords());
                if(m2.find()){
                    o.setE2(m2.group(1));
                }
            }
        });
        ExcelKit.$Export(Railway.class, response).downXlsx(railways, false);
    }
}
